/*
 * Copyright (c) 2010 Mathias Garbe <code@mathias-garbe.de>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#ifndef MAINWINDOW_HPP
#define MAINWINDOW_HPP

#include "Update.hpp"
#include "OnlineStatus.hpp"
#include "GameWindow.hpp"
#include "SettingsWindow.hpp"
#include "GameSelectWindow.hpp"
#include <QtGui/QMainWindow>
#include <QImage>
#include <QPainter>
#include <QSettings>
#include <QMessageBox>
#include <QStandardItemModel>
#include <QSystemTrayIcon>
#include <QTimer>
#include <QTime>
#include <QDesktopServices>
#include "ui_MainWindow.h"

class OnlineStatus;
class GameInfo;
class Update;
class SettingsWindow;
class GameWindow;
class GameSelectWindow;

class MainWindow : public QMainWindow
{
	Q_OBJECT

public:
	MainWindow(QWidget *parent = 0, Qt::WFlags flags = 0);
    ~MainWindow();

    void show();

    bool closed;

    void refreshGames();
    void updateOnlineStatus();

    void checkIrc();
    void rebuildTabs();

private:
    Ui::MainWindowClass ui;

    void changeEvent(QEvent *event);
    void closeEvent(QCloseEvent *event);
    void paintEvent(QPaintEvent *event);
    void mouseReleaseEvent(QMouseEvent *event);

    QRect getGameButtonRect(int gameID);

    void startGame(int gameID);

    // Online status
    OnlineStatus *onlineStatus;

    int curGameID;

    QImage logo;
    QImage gameImg[5];

    // Model for OnlinePlayer list
    QStandardItemModel *model;

    QSystemTrayIcon *trayIcon;

    // Windows
    SettingsWindow *settingsWin;
    GameWindow *gameWin;
    GameSelectWindow *gameSelectWin;
 
    ThreadingVector<Packet> *incomingPackets, *outgoingPackets;

    // IRC
    IrcClient::Session *session;


    void addIrcMessage(QString msg)
    {
        /*bool appendNewline = false;
        QString tmp = this->ui.textIrcChat->toPlainText();
        if(tmp.length() != 0)
        {
            appendNewline = true;
        }*/       

        QString tmp = this->ui.textIrcChat->toHtml();

        QSettings settings;
        bool timestamp = settings.value("IRC/Timestamp", false).toBool();

        if(timestamp)
        {
            QTime time = QTime::currentTime();
            tmp.append(time.toString(Qt::TextDate)).append("&nbsp;&nbsp;");

        }

        tmp.append(msg);

        /*if(appendNewline)
        {
            tmp.append("");
        }*/

        this->ui.textIrcChat->setHtml(tmp);

        QTextCursor c = this->ui.textIrcChat->textCursor();
        c.movePosition(QTextCursor::End);
        this->ui.textIrcChat->setTextCursor(c);
        this->ui.textIrcChat->ensureCursorVisible();

    }

public slots:

    void ircOnNewChatline(QString msg)
    {
        this->addIrcMessage(msg);
    }

    void ircOnClearChat()
    {
        this->ui.textIrcChat->setPlainText("");
    }

    void ircOnNicklist(QStringList nicks)
    {
        int max = this->ui.listIrcNick->count();

        for(int i=0;i<max;i++)
        {
            this->ui.listIrcNick->takeItem(0);
        }

        for (int i = 0; i < nicks.size(); ++i)
        {
            this->ui.listIrcNick->addItem(nicks.at(i));
        }
    }

    void ircOnTopic(QString topic)
    {
        QString tmp;
        tmp.append("<b>Topic:</b> ").append(topic);
        this->ui.labelIrcTopic->setText(tmp);
    }

    void ircOnDisconnect()
    {
        checkIrc();
    }

    void ircDisconnect()
    {
        if(this->session != 0)
        {
            delete this->session;
            this->session = 0;

            this->addIrcMessage("-!- Disconnected.");

            QSettings settings;
            settings.setValue("IRC/Enabled", false);
            settings.sync();
        }
    }

private slots:

    void onSendIrcMessage();


	void aboutBox()
    {
        std::stringstream text;
        text << "CnCnet Client Build No. '" << _BUILD_VERSION << "'\nBy: Toni Spets (Server and launcher code), Mathias Garbe (GUI and additional code)\n\n";
        text << "Contributors:\nTore (Webspace, game logos, cnc-comm.com webmaster)\ngodly-cheese (Game logos, spellchecking)";
        text << "\n\nSpecial thanks to: Myg, Irony";
        text << "\n\nPermission to use, copy, modify, and distribute this software for any ";
        text << "purpose with or without fee is hereby granted, provided that the above ";
        text << "copyright notice and this permission notice appear in all copies.";
        text << "\n\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ";
        text << "WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ";
        text << "MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ";
        text << "ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ";
        text << "WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ";
        text << "ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF ";
        text << "OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.";

        QMessageBox::about(this, tr("About CnCnet"), text.str().c_str());
    }

	void openOnlineHelp()
	{
		linkClicked(QUrl("http://cncnet.cnc-comm.com/?page=setup"));
	}

	void openForums()
	{
		linkClicked(QUrl("http://www.cnc-comm.com/community/index.php?board=78.0"));
	}

	void openIRC()
	{
		linkClicked(QUrl("http://webchat.freenode.net/?channels=cncnet"));
	}

    void startTD() { this->startGame(0); }
    void startRA() { this->startGame(1); }
    void startTS() { this->startGame(2); }
    void startRA2() { this->startGame(3); }
    void startRA2YR() { this->startGame(4); }

    void menuRefreshGames()
    {
        this->refreshGames();
    }

    void openSettings();
    void checkForUpdates();

    void systrayActivated(QSystemTrayIcon::ActivationReason reason)
    {
        QSettings settings;
        if(reason == QSystemTrayIcon::DoubleClick && settings.value("General/MinimizeToTray", true).toBool())
        {
            showNormal();
            activateWindow();
            return;
        }
    }

    void linkClicked(const QUrl &url)
    {
        QDesktopServices::openUrl(url);
    }
};

#endif

/*
virtual
void
changeEvent(QEvent * event)
{
if(event->type() == QEvent::WindowStateChange &&
isMinimized() &&
m_settings.minimizeToTray())
{
m_minimized_to_tray                      = true;
m_window_state_before_minimizing_to_tray =
static_cast<QWindowStateChangeEvent*>(event)->oldState();

QTimer::singleShot(0,this,SLOT(hide()));
}
QMainWindow::changeEvent(event);
}



void
toggleMainWindowVisibility()
{
if(isMinimized())
{
LOG_DEBUG("Window is minimized...");
if(m_minimized_to_tray)
{
LOG_DEBUG("Minimized to tray... Showing");
m_minimized_to_tray = false;
setVisible(true);
// Don't know why setting window state is needed :(
setWindowState(m_window_state_before_minimizing_to_tray | Qt::WindowActive);
activateWindow();
LOG_DEBUG("Shown...");
}
else
{
LOG_DEBUG("Not minimized to tray... Showing");
showNormal();
activateWindow();
LOG_DEBUG("Shown");
}
}
else if (!isVisible())
{
LOG_DEBUG("Not minimized, showing..");
show();
activateWindow();
}
else
{
LOG_DEBUG("Neither minimized nor hidden, hiding");
hide();
}
}

*/
